#ifndef _HASHTABLE_H_
#define _HASHTABLE_H_

#define HASHTABLE_SIZE 8

struct fingerprint_node{
	struct fingerprint_node* next;
	struct fingerprint_node* previous;
	unsigned long fingerprint;
	unsigned int count;
};

struct ipSrc_node{
	struct ipSrc_node* next;
	struct ipSrc_node* previous;
	unsigned long ipSrc;
	unsigned int count;
};


struct destPort_node{
	struct destPort_node* next;
	struct destPort_node* previous;
	unsigned long destPort;
	unsigned int count;
};
int packets_processed;

//Functions
void hashtable_init(struct fingerprint_node* f[HASHTABLE_SIZE], struct ipSrc_node* s[HASHTABLE_SIZE], struct destPort_node* d[HASHTABLE_SIZE]);

void addFingerprint(struct fingerprint_node* h[HASHTABLE_SIZE],  struct node_packet *node, int* lock);
void addIpSrc(struct ipSrc_node* h[HASHTABLE_SIZE],  struct node_packet *node, int* lock);
void addDestPort(struct destPort_node* h[HASHTABLE_SIZE],  struct node_packet *node, int* lock);

void removeFingerprint(struct fingerprint_node* h[HASHTABLE_SIZE], struct node_packet *node, int* lock);
void removeIpSrc(struct ipSrc_node* h[HASHTABLE_SIZE], struct node_packet *node, int* lock);
void removeDestPort(struct destPort_node* h[HASHTABLE_SIZE], struct node_packet *node, int* lock);


int containsFingerprint(struct fingerprint_node* h[HASHTABLE_SIZE], struct node_packet *node, int* lock);
int containsIpSrc(struct ipSrc_node* h[HASHTABLE_SIZE], struct node_packet *node, int* lock);
int containsDestPort(struct destPort_node* h[HASHTABLE_SIZE], struct node_packet *node, int* lock);
unsigned long djb2(unsigned char *pkt, int n);

void inc_processed();

void print_stats(struct fingerprint_node* f[HASHTABLE_SIZE], struct ipSrc_node* s[HASHTABLE_SIZE], struct destPort_node* d[HASHTABLE_SIZE], int* fLock, int* iLock, int* dLock);
#endif
